using DevCangjie.Dto;
using Microsoft.UI;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text.RegularExpressions;
using Windows.Foundation;
using Windows.Foundation.Collections;
using DevCangjie.utils.Settings;
using DevCangjie.utils.MathUtils;
using DevCangjie.Pages.ConsolePage;
using Microsoft.UI.Xaml.Documents;
using Microsoft.UI.Text;
using Windows.UI;
using Windows.UI.Core;
using Windows.UI.Text;
using Windows.UI.ViewManagement;
using Windows.Storage;
using Windows.System;
using System.Numerics;

// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
using Microsoft.UI.Dispatching;
using DevCangjie.utils.Highlight;
using System.Threading.Tasks;
using Windows.Storage.Pickers;
using Windows.Storage.Streams;
using WinUIEditor;
using System.Globalization;
using System.Windows.Media.TextFormatting;
using DevCangjie.utils.CommandRunner;
using Microsoft.UI.Xaml.Hosting;

namespace DevCangjie.Pages.EditPage
{
    public sealed partial class EditPage : Page
    {
        private int _lastSearchIndex = 0;

        /// <summary>
        /// Defines the default style attributes applied to all styles when SCI_STYLECLEARALL is invoked.
        /// </summary>
        private const int STYLE_DEFAULT = 32;

        /// <summary>
        /// Sets the attributes for the text used to display line numbers in the line number margin.
        /// The background color of this style also applies to margins without folding masks.
        /// </summary>
        private const int STYLE_LINENUMBER = 33;

        /// <summary>
        /// Specifies the attributes used when highlighting matching braces using SCI_BRACEHIGHLIGHT.
        /// Also used for highlighting corresponding indentation with SCI_SETHIGHLIGHTGUIDE.
        /// </summary>
        private const int STYLE_BRACELIGHT = 34;

        /// <summary>
        /// Sets the display attributes for unmatched braces, triggered by SCI_BRACEBADLIGHT.
        /// </summary>
        private const int STYLE_BRACEBAD = 35;

        /// <summary>
        /// Defines the font used for drawing control characters.
        /// Only font-related attributes (font face, size, bold, italics, character set) are applied.
        /// </summary>
        private const int STYLE_CONTROLCHAR = 36;

        /// <summary>
        /// Sets the foreground and background colors for drawing indentation guides.
        /// </summary>
        private const int STYLE_INDENTGUIDE = 37;

        /// <summary>
        /// Specifies the style for call tips. Typically uses STYLE_DEFAULT attributes unless SCI_CALLTIPUSESTYLE is enabled.
        /// Only font face, size, and color attributes are applied.
        /// </summary>
        private const int STYLE_CALLTIP = 38;

        /// <summary>
        /// Defines the style used for drawing text tags attached to folded text regions.
        /// </summary>
        private const int STYLE_FOLDDISPLAYTEXT = 39;

        /// <summary>
        /// Represents the last predefined style number to help in discovering the range of predefined styles.
        /// </summary>
        private const int STYLE_LASTPREDEFINED = 39;

        /// <summary>
        /// Denotes the maximum style number that can be set. Styles between STYLE_LASTPREDEFINED and STYLE_MAX can be used for custom purposes.
        /// </summary>
        private const int STYLE_MAX = 255;
        private List<LineEditModel> _fonts;
        public List<LineEditModel> Fonts => _fonts;

        private string _filePath;
        public string FilePath
        {
            get => _filePath;
            set => _filePath = value;
        }

        private bool _saved;
        public bool IsSaved
        {
            get => _saved;
            set => _saved = value;
        }
        private string _textBeforeSave;
        private DispatcherTimer _saveCheckTimer;

        public EditPage()
        {
            _fonts = new List<LineEditModel>() { new LineEditModel(1) };
            this.InitializeComponent();

            _filePath = "";
            _saved = false;

            CodeArea.Editor.Modified += CodeArea_TextChanged;
            SetEditorFontLocale();
            SetEditorFont();
            InitializeSaveCheckTimer();

            // 订阅 FindReplaceControl 的关闭事件
            FindReplaceControl.CloseRequested += FindReplaceControl_CloseRequested;

            // 设置 ParentEditPage 引用
            FindReplaceControl.ParentEditPage = this;
        }
        public EditPage(string content) : this()
        {
            CodeArea.Editor.SetText(content);
            _filePath = "";
            _textBeforeSave = content;
        }

        public EditPage(StorageFile filePath) : this()
        {
            string content = File.ReadAllText(filePath.Path);
            CodeArea.Editor.SetText(content);
            _filePath = filePath.Path;
            _textBeforeSave = content;
            _saved = false;
        }

        public void ApplySettings()
        {
            // 更新编辑器字体和样式
            SetEditorFontLocale();
            SetEditorFont();

            // 更新字体大小
            CodeArea.FontSize = Settings.Instance.StyleDefaultFontSize;

            // 更新字体
            CodeArea.FontFamily = Settings.Instance.StyleDefaultFont;

            // 更新其他 EditPage 相关属性设置
        }

        public string GetContent()
        {
            return CodeArea.Editor.GetText(CodeArea.Editor.Length); // 假设 CodeArea 是编辑器控件
        }

        // 添加快捷键事件处理程序
        private void FindReplace_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
        {
            ShowFindReplaceWindow();
            args.Handled = true;
        }

        private void CodeArea_TextChanged(Editor sender, ModifiedEventArgs args)
        {
            _saveCheckTimer.Stop();
            _saveCheckTimer.Start();
        }
        private void SetEditorFontLocale()
        {
            // 获取系统区域设置
            CultureInfo currentCulture = CultureInfo.CurrentUICulture;
            string localeName = currentCulture.Name;

            // 设置字体区域
            CodeArea.Editor.SetFontLocale(localeName);
        }
        private void InitializeSaveCheckTimer()
        {
            _saveCheckTimer = new DispatcherTimer();
            _saveCheckTimer.Interval = TimeSpan.FromSeconds(1);
            _saveCheckTimer.Tick += SaveCheckTimer_Tick;
            _saveCheckTimer.Start();
        }

        private void SaveCheckTimer_Tick(object sender, object e)
        {
            string text = CodeArea.Editor.GetText(CodeArea.Editor.Length);
            if (text != _textBeforeSave)
            {
                IsSaved = false;
            }
        }
        private void SetEditorFont()
        {
            // 设置 STYLE_DEFAULT 的字体和字号
            CodeArea.Editor.StyleSetFont(STYLE_DEFAULT, Settings.Instance.StyleDefaultFont.Source);
            CodeArea.Editor.StyleSetSize(STYLE_DEFAULT, Settings.Instance.StyleDefaultFontSize);

            // 设置 STYLE_LINENUMBER 的字体和字号
            CodeArea.Editor.StyleSetFont(STYLE_LINENUMBER, Settings.Instance.StyleLineNumberFont.Source);
            CodeArea.Editor.StyleSetSize(STYLE_LINENUMBER, Settings.Instance.StyleLineNumberFontSize);

            // 设置 STYLE_BRACELIGHT 的字体和字号
            CodeArea.Editor.StyleSetFont(STYLE_BRACELIGHT, Settings.Instance.StyleBraceLightFont.Source);
            CodeArea.Editor.StyleSetSize(STYLE_BRACELIGHT, Settings.Instance.StyleBraceLightFontSize);

            // 设置 STYLE_BRACEBAD 的字体和字号
            CodeArea.Editor.StyleSetFont(STYLE_BRACEBAD, Settings.Instance.StyleBraceBadFont.Source);
            CodeArea.Editor.StyleSetSize(STYLE_BRACEBAD, Settings.Instance.StyleBraceBadFontSize);

            // 设置 STYLE_CONTROLCHAR 的字体和字号
            CodeArea.Editor.StyleSetFont(STYLE_CONTROLCHAR, Settings.Instance.StyleControlCharFont.Source);
            CodeArea.Editor.StyleSetSize(STYLE_CONTROLCHAR, Settings.Instance.StyleControlCharFontSize);

            // 设置 STYLE_INDENTGUIDE 的字体和字号
            CodeArea.Editor.StyleSetFont(STYLE_INDENTGUIDE, Settings.Instance.StyleIndentGuideFont.Source);
            CodeArea.Editor.StyleSetSize(STYLE_INDENTGUIDE, Settings.Instance.StyleIndentGuideFontSize);

            // 设置 STYLE_CALLTIP 的字体和字号
            CodeArea.Editor.StyleSetFont(STYLE_CALLTIP, Settings.Instance.StyleCallTipFont.Source);
            CodeArea.Editor.StyleSetSize(STYLE_CALLTIP, Settings.Instance.StyleCallTipFontSize);

            // 设置 STYLE_FOLDDISPLAYTEXT 的字体和字号
            CodeArea.Editor.StyleSetFont(STYLE_FOLDDISPLAYTEXT, Settings.Instance.StyleFoldDisplayTextFont.Source);
            CodeArea.Editor.StyleSetSize(STYLE_FOLDDISPLAYTEXT, Settings.Instance.StyleFoldDisplayTextFontSize);
        }
        public static int GetLineCountFromString(string text)
        {
            int lineCount = 0;
            try
            {
                var lines = Regex.Split(text.Trim(), "\r");
                lineCount = lines.Length;
            }
            catch (Exception e)
            {
                // 处理异常
                ConsolePage.ConsolePage.Instance.AppendErrorOutput(e.ToString());

            }
            return lineCount;
        }
        private void CodeEditorControl_Loaded(object sender, RoutedEventArgs e)
        {
            ((Control)sender).Focus(FocusState.Programmatic);
        }
        public async Task SaveAsync(Window window)
        {
            if (string.IsNullOrEmpty(FilePath))
            {
                await SaveAsAsync(window);
                return;
            }
            long length = CodeArea.Editor.Length;
            string text = CodeArea.Editor.GetText(length);
            //ConsolePage.ConsolePage.Instance.AppendInfoOutput($"text length {length},text : {text}");
            await File.WriteAllTextAsync(FilePath, text, System.Text.Encoding.UTF8);
            IsSaved = true;
            _textBeforeSave = text;
        }

        public async Task SaveAsAsync(Window window)
        {
            var picker = new FileSavePicker();
            picker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
            picker.FileTypeChoices.Add("文本文件", new List<string>() { ".cj" });
            var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(window);
            WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd);
            StorageFile file = await picker.PickSaveFileAsync();
            if (file != null)
            {
                long length = CodeArea.Editor.Length;
                string text = CodeArea.Editor.GetText(length);
                //ConsolePage.ConsolePage.Instance.AppendInfoOutput($"text length {length},text : {text}");
                await FileIO.WriteTextAsync(file, text, UnicodeEncoding.Utf8);
                IsSaved = true;
                _textBeforeSave = text;
                FilePath = file.Path;
                // Optionally update the tab header if applicable
            }
            else
            {
                // User canceled the save operation
            }
        }
        /// <summary>
        /// 编译当前文件
        /// </summary>
        public async Task<bool> CompileAsync(bool showDialog = true)
        {
            string filePath = this.FilePath;
            if (string.IsNullOrEmpty(filePath))
            {
                await SaveAsAsync(MainWindow.Current);
                filePath = this.FilePath;
                if (string.IsNullOrEmpty(filePath))
                {
                    ConsolePage.ConsolePage.Instance.AppendErrorOutput("保存文件后才能编译！");
                    return false;
                }
            }
            else
            {
                await SaveAsync(MainWindow.Current);
            }

            // 执行编译逻辑
            bool success = await CommandRunner.CompileCangjieSingleFileAsync(filePath, filePath + ".exe");
            if (success)
            {
                ConsolePage.ConsolePage.Instance.AppendInfoOutput("-----编译成功-----");
                if (showDialog)
                {
                    await new ContentDialog
                    {
                        Title = "编译完成",
                        Content = "代码已成功编译。",
                        CloseButtonText = "确定",
                        XamlRoot = this.XamlRoot
                    }.ShowAsync();
                }
                return true;
            }
            else
            {
                ConsolePage.ConsolePage.Instance.AppendErrorOutput("-----编译失败-----");
                if (showDialog)
                {
                    await new ContentDialog
                    {
                        Title = "编译失败",
                        Content = "代码编译时发生错误。",
                        CloseButtonText = "确定",
                        XamlRoot = this.XamlRoot
                    }.ShowAsync();
                }
                return false;
            }
        }

        /// <summary>
        /// 运行当前编译的程序
        /// </summary>
        public async Task RunAsync()
        {
            string filePath = this.FilePath;
            if (string.IsNullOrEmpty(filePath))
            {
                await SaveAsAsync(MainWindow.Current);
                filePath = this.FilePath;
                if (string.IsNullOrEmpty(filePath))
                {
                    ConsolePage.ConsolePage.Instance.AppendErrorOutput("保存文件后才能运行！");
                    return;
                }
            }
            else
            {
                await SaveAsync(MainWindow.Current);
            }

            string exePath = filePath + ".exe";
            if (!File.Exists(exePath))
            {
                ConsolePage.ConsolePage.Instance.AppendErrorOutput("可执行文件不存在，请先编译！");
                return;
            }

            // 执行运行逻辑
            int success = CommandRunner.RunProgram(exePath, "");
            if (success == 0)
            {
                ConsolePage.ConsolePage.Instance.AppendInfoOutput("运行成功！");
            }
            else
            {
                ConsolePage.ConsolePage.Instance.AppendErrorOutput("运行失败！");
                await new ContentDialog
                {
                    Title = "运行失败",
                    Content = "程序运行时发生错误。",
                    CloseButtonText = "确定",
                    XamlRoot = this.XamlRoot
                }.ShowAsync();
            }
        }

        /// <summary>
        /// 编译并运行当前文件
        /// </summary>
        public async Task CompileAndRunAsync()
        {
            bool compileSuccess = await CompileAsync(showDialog: false);
            if (compileSuccess)
            {
                await RunAsync();
            }
            else
            {
                // Optionally, handle the failure case here if needed
                ConsolePage.ConsolePage.Instance.AppendErrorOutput("编译失败，程序未运行。");
            }
        }

        // 显示查找替换 CommandBar
        public void ShowFindReplaceWindow()
        {
            FindReplaceBorder.Visibility = Visibility.Visible;
        }

        // 隐藏查找替换 CommandBar
        private void HideFindReplaceWindow()
        {
            FindReplaceBorder.Visibility = Visibility.Collapsed;
        }

        // 处理关闭事件
        private void FindReplaceControl_CloseRequested(object sender, RoutedEventArgs e)
        {
            HideFindReplaceWindow();
        }

        public void FindNext(string searchText, bool isMatchCase)
        {
            if (string.IsNullOrEmpty(searchText))
            {
                return;
            }

            StringComparison comparison = isMatchCase ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase;
            string editorText = CodeArea.Editor.GetText(CodeArea.Editor.Length);

            int index = editorText.IndexOf(searchText, _lastSearchIndex, comparison);
            if (index == -1 && _lastSearchIndex != 0)
            {
                index = editorText.IndexOf(searchText, 0, StringComparison.CurrentCultureIgnoreCase);
            }

            if (index >= 0)
            {
                CodeArea.Editor.SetSelection(index, index + searchText.Length);
                CodeArea.Editor.ScrollCaret();
                _lastSearchIndex = index + searchText.Length;
            }
            else
            {
                _lastSearchIndex = 0;
                // 可选：提示未找到
            }
        }

        public void Replace(string searchText, string replaceText, bool isMatchCase)
        {
            if (CodeArea.Editor.SelectionEnd - CodeArea.Editor.SelectionStart > 0)
            {
                string selectedText = CodeArea.Editor.GetSelText();
                StringComparison comparison = isMatchCase ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase;

                if (string.Equals(selectedText, searchText, comparison))
                {
                    CodeArea.Editor.ReplaceSel(replaceText);
                }
            }
            FindNext(searchText, isMatchCase);
        }

        public async Task ReplaceAllAsync(string searchText, string replaceText, bool isMatchCase)
        {
            if (string.IsNullOrEmpty(searchText))
            {
                return;
            }

            // 设置正则选项
            RegexOptions options = isMatchCase ? RegexOptions.None : RegexOptions.IgnoreCase;

            string editorText = CodeArea.Editor.GetText(CodeArea.Editor.Length);

            // 统计匹配的次数
            int replacementCount = Regex.Matches(editorText, Regex.Escape(searchText), options).Count;

            // 执行替换
            string newText = Regex.Replace(editorText, Regex.Escape(searchText), replaceText, options);

            CodeArea.Editor.SetText(newText);
            _lastSearchIndex = 0;

            // 显示替换次数的弹窗
            ContentDialog dialog = new ContentDialog
            {
                Title = "替换完成",
                Content = $"已替换 {replacementCount} 处。",
                CloseButtonText = "确定",
                DefaultButton = ContentDialogButton.Close,
                XamlRoot = this.XamlRoot
            };
            await dialog.ShowAsync();
        }


    }
}